﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.DependencyInjection;
using Lrd.Template.Core.Infrastructure.Dependency;
using Lrd.Template.Core.Infrastructure.Entity;
using Lrd.Template.Core.Infrastructure.Exceptions;
using Lrd.Template.Core.Infrastructure.Extensions;
using Lrd.Template.Core.Infrastructure.Ui;

namespace Lrd.Template.Core.Infrastructure.Entity
{
    /// <summary>
    /// 工作单元
    /// </summary>
    public class UnitOfWork<TDbContext> : IUnitOfWork where TDbContext : DbContextBase
    {
        private readonly DbContextBase _dbContext = null;

        /// <summary>
        /// 是否提交 
        /// </summary>
        public bool HasCommitted { get; private set; }

        /// <summary>
        /// 事务
        /// </summary>
        private IDbContextTransaction _transaction = null;

        private bool _disposed;



        public UnitOfWork(TDbContext dbContext)
        {
            _dbContext = dbContext as DbContextBase;
          }

        /// <summary>
        /// 开启事务
        /// </summary>
        public virtual void BeginTransaction()
        {

            if (_transaction == null)
            {
                _transaction = GetTransaction();
            }
            HasCommitted = false;
        }

        /// <summary>
        /// 开启事务异步
        /// </summary>
        public virtual async Task BeginTransactionAsync(CancellationToken cancellationToken = default(CancellationToken))
        {


            if (_transaction == null)
            {
                _transaction = await GetTransactionAsync();
            }

            HasCommitted = false;
        }

        /// <summary>
        /// 提交事务
        /// </summary>
        public void Commit()
        {

            if (HasCommitted)
            {
                return;
            }

            if (_transaction != null)
            {
                try
                {
                    _transaction.Commit();
                }
                catch (Exception e)
                {
                    _transaction.Rollback();
                    HasCommitted = true;
                    throw e;
                }
            }
            HasCommitted = true;
        }



        /// <summary>
        /// 得到事务
        /// </summary>
        /// <returns></returns>

        private IDbContextTransaction GetTransaction()
        {
            return this.Database().BeginTransaction();
        }

        /// <summary>
        /// 得到异步事务
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        private async Task<IDbContextTransaction> GetTransactionAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            return await this.Database().BeginTransactionAsync(cancellationToken);
        }

        /// <summary>
        /// 得到Database
        /// </summary>
        /// <returns></returns>
        private DatabaseFacade Database()
        {
            return this.GetDbContext().Database;
        }

        /// <summary>
        /// 得到上下文
        /// </summary>
        /// <returns></returns>
        public DbContext GetDbContext()
        {
            _dbContext.UnitOfWork = this;
            return _dbContext as DbContext;
        }


        /// <summary>释放对象.</summary>
        public void Dispose()
        {
            if (_disposed)
            {
                return;
            }
            _transaction?.Dispose();
            _disposed = true;
        }

        public void Rollback()
        {
            if (_transaction != null)
            {
                _transaction.Rollback();
            }
            HasCommitted = true;
        }
    }
}
